/*
 * Copyright(C) 2022. Huawei Technologies Co.,Ltd. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <cstring>
#include <fcntl.h>
#include <sys/stat.h>
#include <algorithm>
#include <map>
#include <memory>
#include <vector>

#include "opencv2/imgproc.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/types_c.h"

#include "MxBase/MxBase.h"
#include "MxBase/MemoryHelper/MemoryHelper.h"
#include "MxBase/DeviceManager/DeviceManager.h"
#include "MxBase/Log/Log.h"
#include "PostProcess.h"

using namespace MxBase;
using namespace std;

const int MODEL_INPUT_WIDTH = 640;
const int MODEL_INPUT_HEIGHT = 640;
const int RGB_EXTEND = 3;
const int PAD_COLOR = 114;
const int OPENCV_8UC3 = 16;
const int YUV_DIVISION = 2;
const int R_CHANNEL = 2;
const int AVG_PARAM = 2;
const int ARG_NUM = 10;
const long MAX_FILE_SIZE = 1024 * 1024 * 1024; // 1g

const float YUV_Y_R = 0.299;
const float YUV_Y_G = 0.587;
const float YUV_Y_B = 0.114;
const float YUV_U_R = -0.169;
const float YUV_U_G = 0.331;
const float YUV_U_B = 0.500;
const float YUV_V_R = 0.500;
const float YUV_V_G = 0.419;
const float YUV_V_B = 0.081;
const int YUV_DATA_SIZE = 3;
const int YUV_OFFSET = 2;
const int YUV_OFFSET_S = 1;
const int YUV_OFFSET_UV = 128;
const int ALIGN_LEFT = 16;


class DetectionInfer {
public:
	DetectionInfer();
	virtual ~DetectionInfer();
	APP_ERROR Init();

	void drawBoundingBox(cv::Mat& image, const std::string& className, int x0, int y0, int x1, int y1);

	APP_ERROR CheckFileVaild(const std::string &filePath);

	std::vector<std::vector<ObjectInfo>> SDKPostProcess(std::vector<Tensor> &yolov7Outputs,
		       	                  std::vector<ResizedImageInfo> &imagePreProcessInfos);

	APP_ERROR PaddingProcess(ImageProcessor &imageProcessor, std::pair<int, int> resizeInfo, Image &resizeImage, Image &pastedImg);
	APP_ERROR SetImageBackground(MxBase::MemoryData& data);

	APP_ERROR DvppPreprocessorYuv(ImageProcessor &imageProcessor, std::string &imagePath, vector<Tensor> &yolov7Inputs,
    		std::vector<ResizedImageInfo> &imagePreProcessInfos);

	APP_ERROR OpenCVPreProcessor(std::string &imagePath, vector<Tensor> &yolov7Inputs,
    		std::vector<ResizedImageInfo> &imagePreProcessInfos);

	APP_ERROR DvppPreprocessor(std::string &imagePath, vector<Tensor> &yolov7Inputs,
    		std::vector<ResizedImageInfo> &imagePreProcessInfos);

	std::string E2eInfer(const std::vector<uint8_t> &path, double objThre=0.2, double ioutThre=0.5);
private:

	bool        m_isYuvInput = false;
	int32_t     m_npuDeviceId = 0;
	std::string m_model_path = "./model/detection.om";
	std::string m_config_path = "./model/detection.cfg";
	std::string m_label_path = "./model/labels.names";

	std::shared_ptr<Yolov7PostProcess> m_pModelPostProcess;	
	std::shared_ptr<Model> 		   m_pModel;
};

